home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / BARNET / COMPILER / SATHER / !Sather / Library / Containrs / sa / set_incl < prev    next >
Text File  |  1996-07-13  |  12KB  |  343 lines

  1. ---------------------------> Sather 1.1 source file <--------------------------
  2. -- set_incl.sa: Set include partial classes
  3. -- Author: Benedict A. Gomes <gomes@samosa.ICSI.Berkeley.EDU>
  4. -- Copyright (C) 1995, International Computer Science Institute
  5. -- $Id: set_incl.sa,v 1.10 1996/07/13 05:41:11 gomes Exp $
  6. --
  7. -- COPYRIGHT NOTICE: This code is provided WITHOUT ANY WARRANTY
  8. -- and is subject to the terms of the SATHER LIBRARY GENERAL PUBLIC
  9. -- LICENSE contained in the file: Sather/Doc/License of the
  10. -- Sather distribution. The license is also available from ICSI,
  11. -- 1947 Center St., Suite 600, Berkeley CA 94704, USA.
  12. -------------------------------------------------------------------
  13. partial class RO_SET_INCL{E} < $RO_SET{E} is
  14.    -- Partial class for $RO_SET{E} that implements other functions
  15.    -- in terms of has and elt!
  16.    -- 
  17.    private include COMPARE{E};
  18.    
  19.    stub has(e: E): BOOL;
  20.    -- Return true if the class has the element "e"
  21.    
  22.    stub elt!: E;
  23.    -- Yield the elements of the set
  24.    
  25.    stub copy: SAME;
  26.    -- Return a copy of the set
  27.    
  28.    private create_from_internal(s: $RO_SET{E}): SET{E} is
  29.       -- Used as an auxilliary routine by the view creation routines.
  30.       -- When the return type can be any $RO_SET, then by default a
  31.       -- "SET" will be constructed and used
  32.       return #SET{E}(s);
  33.    end;
  34.  
  35.    --              ------ Access/Measurement -------------
  36.    size: INT is 
  37.       i ::= 0; loop discard ::= elt!; i := i + 1; end;
  38.       return i;
  39.    end;
  40.    
  41.    is_empty: BOOL pre ~void(self) is  
  42.       -- Do not do size=0. Finding size may require iteration
  43.       -- through all elements - quite wasteful for just "is_empty"
  44.       loop e ::= elt!; return false; end;
  45.       return true;
  46.    end;
  47.  
  48.    --              ------ Queries/Comparison --------------
  49.    equals(a:$RO_SET{E}): BOOL     pre ~void(self) and ~void(a)   is
  50.       -- Returns 'true' if every element of self is elt_eq to
  51.       -- an element in 'a' and vice versa.
  52.       -- Neither may be void.
  53.       if a.size /= size then return false end;
  54.       loop e ::= a.elt!; 
  55.      if ~has(e) then   return false end 
  56.       end;
  57.       -- The second loop could be replaced against
  58.       -- 'return size = a.size' but this won't work for
  59.       -- some types of elements.
  60.       loop if ~a.has(elt!) then   return false; end  end;
  61.       return true
  62.     end;
  63.  
  64.    --              ------ Conversion ----------------------
  65.    as_array: ARRAY{E} is
  66.       res ::= #ARRAY{E}(size);
  67.       loop res.set!(elt!) end;
  68.       return res;
  69.    end;
  70.  
  71.    str: STR is
  72.       -- Prints out a string version of the array of the components 
  73.       -- that are under $STR
  74.       res ::= #FSTR("{");
  75.       loop  e ::= elt!;
  76.      typecase e
  77.      when $STR then res := res+",".separate!(e.str); 
  78.      else res := res+",".separate!("unprintable"); end;
  79.       end;
  80.       res := res + "}";
  81.       return(res.str);
  82.    end;
  83.    
  84.    --              ------ Basic Operations ---------------- 
  85.    union(s: $RO_SET{E}): SET{E} is
  86.       -- Union is defined by default to create a "view" and then convert
  87.       -- that into a SET.  Subtypes may redefine this behavior to return
  88.       -- a set of type "SAME", without going through a view
  89.       return create_from_internal(union_view(s)); 
  90.    end;
  91.    
  92.    intersection(s:$RO_SET{E}): SET{E} is
  93.       -- See the comment for "union" and $RO_SET::intersection
  94.       return create_from_internal(intersection_view(s)) 
  95.    end;
  96.  
  97.    diff(s: $RO_SET{E}): SET{E} is
  98.       -- See the comment for "union" and $RO_SET::diff
  99.       return create_from_internal(diff_view(s)) 
  100.    end;
  101.    
  102.    sym_diff(s: $RO_SET{E}): SET{E} is
  103.       -- See the comment for "union" and $RO_SET::sym_diff
  104.       return create_from_internal(sym_diff_view(s)) 
  105.    end;
  106.    
  107.    union_view(s: $RO_SET{E}): $RO_SET{E} is
  108.       -- Return a read-only "view" of the union of "self" and "s"
  109.       -- The resulting view just points to the two component sets
  110.       -- and computes its elements on-the-fly, as needed.
  111.       -- As a result, this form of union requires almost no
  112.       -- additional space but may it may take slightly longer to 
  113.       -- perform operations
  114.       return BINOP_SET_VIEW{E}::create_union(get_set_of_self,s); 
  115.    end;
  116.    
  117.    intersection_view(s: $RO_SET{E}): $RO_SET{E} is
  118.       -- See the note for "union_view"
  119.       return BINOP_SET_VIEW{E}::create_intersection(get_set_of_self,s);
  120.    end;
  121.    
  122.    diff_view(s: $RO_SET{E}): $RO_SET{E} is
  123.       -- See the comment for "union_view"
  124.       return BINOP_SET_VIEW{E}::create_diff(get_set_of_self,s);
  125.    end;
  126.    
  127.    sym_diff_view(s: $RO_SET{E}): $RO_SET{E} is
  128.       -- See the comment for "union_view"
  129.       return BINOP_SET_VIEW{E}::create_sym_diff(get_set_of_self,s);
  130.    end;
  131.    
  132.    is_subset_of(s: $RO_SET{E}): BOOL is
  133.       -- Return true if "self" is a subset of "s"
  134.       return diff_view(s).is_empty
  135.    end;
  136.  
  137.    private get_set_of_self: SAME is
  138.       local_self ::= self;
  139.       typecase local_self
  140.       when $RO_SET{E} then return local_self 
  141.       else 
  142.      raise("Partial RO_SET_INCL included in a non-subtype of $RO_SET");
  143.       end;
  144.    end;
  145.         
  146. end;
  147. -------------------------------------------------------------------
  148. partial class SET_INCL{E} < $SET{E} is
  149.     -- SET_INCL defines some of the set functions which are not dependant
  150.     -- on the implementation of the set.
  151.     -- The most common routines (union, intersect etc.) are special cased
  152.     -- so that when the argument is of type SAME there is no dispatching.
  153.     -- Be careful about create 
  154.    include RO_SET_INCL{E};
  155.  
  156.    stub insert(e:E); 
  157.    -- Insert element "e" into the set
  158.    
  159.    stub delete(e:E);
  160.    -- Delete element "e" from the set
  161.    
  162.    stub create: SAME;
  163.    -- Create an empty set - used by the other set create routines
  164.  
  165.    --              ------ Initialization/Duplication ------
  166.    create(a: ARRAY{E}): SAME is
  167.       return create_from(a);
  168.    end;
  169.  
  170.    create_from(e: $ELT{E}): SAME is
  171.       res ::= create;
  172.       loop res.insert(e.elt!) end;
  173.       return res;   
  174.    end;
  175.    
  176.    copy_from(a: $ELT{E}) is
  177.       -- Clear old elts and insert the elements of self
  178.       clear;
  179.       loop insert(a.elt!) end;
  180.    end;
  181.  
  182.    clear is 
  183.       -- Expensive! To make sure that we don't overwrite while
  184.       -- reading, use a seperate array.
  185.       elts: FLIST{E} := #;
  186.       loop elts := elts.push(elt!) end;
  187.       loop delete(elts.elt!) end;
  188.    end;
  189.    
  190.    --              ------ Basic Operations ----------------
  191.    -- Versions that modify self, special cased when the arg is SAME
  192.    to_union(a: $ELT{E}) pre ~void(self) and ~void(a) is
  193.       typecase a 
  194.       when SAME then
  195.      loop e ::= a.elt!; if ~has(e) then insert(e) end end;
  196.       else loop e ::= a.elt!; if ~has(e) then insert(e) end end; end;
  197.    end;
  198.  
  199.    to_diff(a: $ELT{E}) pre ~void(self) and ~void(a) is
  200.       typecase a
  201.       when SAME then loop e ::= a.elt!; if has(e) then delete(e) end  end;
  202.       else loop e ::= a.elt!; if has(e) then delete(e) end  end; end;
  203.    end;
  204.  
  205.    to_sym_diff(a: $ELT{E}) pre ~void(self) and ~void(a) is
  206.       typecase a
  207.       when SAME then
  208.      loop e::=a.elt!; if has(e) then delete(e) else insert(e) end end;
  209.       else 
  210.      loop e::=a.elt!; if has(e) then delete(e) else insert(e) end end;
  211.       end;
  212.    end;      
  213.  
  214.    to_intersection(a: $ELT{E}) is
  215.       typecase a
  216.       when SAME then 
  217.      loop e ::= a.elt!; if ~has(e) then delete(e) end; end;
  218.       else loop e ::= a.elt!; if ~has(e) then delete(e) end; end; end;
  219.    end;
  220.  
  221. end; -- SET_INCL{E}
  222. -------------------------------------------------------------------
  223. class BINOP_SET_VIEW{ETP} < $RO_SET{ETP} is
  224.    -- View of a binary operation between two sets.
  225.    -- Handles union, intersection, diff and sym_diff
  226.    -- Instead of copying the sets, it merely maintains pointers
  227.    -- to the two sets. 
  228.    -- This view is read-only and *cannot* be used to modify the
  229.    -- original sets. Note that it is *not* a value interface.
  230.    -- In fact, if the original sets change, this view will automatically
  231.    -- change. In some cases this is exactly the behavior you want;
  232.    -- in other cases it can be a source of nasty problems. Use carefully.
  233.    -- 
  234.    -- Usage:
  235.    --     s1: $SET{INT} := #SET{INT}(|1,2,3,5|);
  236.    --     s2: $SET{INT} := #SET{INT}(|1,5,3,9|);
  237.    --     s ::= BINOP_SET_VIEW{INT}::create_union(s1,s2);
  238.    --     #OUT+ s.str;
  239.    --      -- will print out the elements 1,2,3,5,9 in some arbitrary order
  240.    --     s2.delete(9);
  241.    --     #OUT+s.str;
  242.    --      -- will print out the elements 1,2,3,5 in some arbitrary order
  243.    -- 
  244.    -- Implementation:
  245.    --     Maintains pointers to the two sets, primary and secondary
  246.    --     The space of the final set is broken down into:
  247.    --     Primary set: (       primary               )  
  248.    --     Seconary set:               (          secondary         )
  249.    --     Result:      ( p_minus_s    ( intersection )  s_minus_p  )
  250.    --    
  251.    --     The flags use_p_minus_s, use_intersect and use_s_minus_p indicate
  252.    --     which part should be used
  253.    include RO_SET_INCL{ETP};
  254.    
  255.    private attr primary: $RO_SET{ETP};
  256.    private attr secondary: $RO_SET{ETP};
  257.    private attr use_p_minus_s: BOOL; -- Use elements in prim-sec
  258.    private attr use_intersect: BOOL;    -- Use elements in prim intersect sec
  259.    private attr use_s_minus_p: BOOL;    -- Use elements in sec - prim
  260.  
  261.    create_union(prim: $RO_SET{ETP},sec: $RO_SET{ETP}): SAME is
  262.       return #(prim,sec,true,true,true);
  263.    end;
  264.    
  265.    create_intersection(prim: $RO_SET{ETP},sec: $RO_SET{ETP}): SAME is
  266.       return #(prim,sec,false,true,false);
  267.    end; 
  268.    
  269.    create_diff(prim: $RO_SET{ETP},sec: $RO_SET{ETP}): SAME is
  270.       return #(prim,sec,true,false,false);
  271.    end; 
  272.    
  273.    create_sym_diff(prim: $RO_SET{ETP},sec: $RO_SET{ETP}): SAME is
  274.       return #(prim,sec,true,false,true);
  275.    end; 
  276.    
  277.    create(prim: $RO_SET{ETP}, sec: $RO_SET{ETP},
  278.       use_p_minus_s: BOOL,use_intersect:BOOL, use_s_minus_p: BOOL): SAME 
  279.    -- The three parameters indicate whether the resulting set should
  280.    -- contain
  281.    -- (a) elements from A-B
  282.    -- (b) elements from A intersection B
  283.    -- (c) elements from B-A
  284.    -- A-B  A in B  B-A
  285.    --  f      f     f = empty
  286.    -- *f      f     t = B-A             
  287.    -- *f      t     f = intersection
  288.    --  f      t     t = B
  289.    -- *t      f     f = A - B
  290.    -- *t      f     t = Symmetric Difference
  291.    --  t      t     f = A
  292.    -- *t      t     t = A union B 
  293.    -- The combinations marked with asterisks are the interesting combinations.
  294.    -- This class was designed thus so as to generate the different interesting
  295.    -- views of a set using a single class rather than creating separate
  296.    -- view classes which generates much more code.
  297.       pre ~void(prim) and ~void(sec)
  298.    is      
  299.       res ::= new;  
  300.       res.primary := prim;  
  301.       res.secondary := sec; 
  302.       res.use_p_minus_s := use_p_minus_s;
  303.       res.use_intersect := use_intersect;
  304.       res.use_s_minus_p := use_s_minus_p;
  305.       return res;
  306.    end;
  307.    
  308.    copy: SAME is
  309.       -- Copy returns a copy of the same type of set
  310.       return #SAME(primary,secondary,use_p_minus_s,use_intersect,use_s_minus_p)
  311.    end;
  312.  
  313.    has(e: ETP): BOOL is 
  314.       -- Return true if "e" belongs to this set
  315.       -- ph = primary has e  sh = secondary has e
  316.       -- * indicates a don't care
  317.       -- ph sh                       p-s  p in s  s-p
  318.       -- T   T  => result is True if  *      t     *
  319.       -- T   F  => result is True if  t      *     *
  320.       -- F   T  =>           True if  *      *     t
  321.       -- F   F  => result is False
  322.       ph ::= primary.has(e);  sh ::= secondary.has(e);
  323.       return (ph and sh and use_intersect) 
  324.         or (ph and use_p_minus_s) 
  325.         or (sh and use_s_minus_p) 
  326.    end;
  327.    
  328.    elt!: ETP is
  329.       if use_p_minus_s and use_intersect then
  330.      loop e ::= primary.elt!; yield e end;
  331.       elsif use_p_minus_s and ~use_intersect then
  332.      loop e ::= primary.elt!; if ~secondary.has(e) then yield e end end;
  333.       elsif ~use_p_minus_s and use_intersect then
  334.      loop e ::= primary.elt!; if secondary.has(e) then yield e end; end;
  335.       end;
  336.       if use_s_minus_p then
  337.      loop e ::= secondary.elt!; if ~primary.has(e) then yield e end; end;
  338.       end;        
  339.    end;
  340.  
  341. end;
  342. -------------------------------------------------------------------
  343.